﻿using BCCommon;
using BCService.Sim.Admin.AdminOperationRecord;
using BCTMSRESTful.Controllers.Management;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BCTMSRESTful.Configs
{
    public class LogAttribute : ActionFilterAttribute
    {
        private readonly string name;
        private IDictionary<string, object> actionArguments;

        public LogAttribute(string name)
        {
            this.name = name;
        }

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            this.actionArguments = context.ActionArguments;
        }

        public override void OnActionExecuted(ActionExecutedContext context)
        {
            if (context.Exception != null)
            {
                return;
            }

            ManagementBaseController managementBaseController = context.Controller as ManagementBaseController;

            if (managementBaseController != null)
            {
                PerformanceTracer.InvokeAsync(delegate
                {
                    IAdminOperationRecordService operationRecordService = managementBaseController.HttpContext.RequestServices.GetService(typeof(IAdminOperationRecordService)) as IAdminOperationRecordService;
                    string value = this.ConvertActionArguments();
                    operationRecordService.Create(this.name, value, managementBaseController.Admin.AdminId, managementBaseController.Admin.LoginName, managementBaseController.Admin.FullName, managementBaseController.Admin.CompanyId);
                });
            }

            //PartnerAppController partnerAppController = context.Controller as PartnerAppController;

            //if (partnerAppController != null)
            //{
            //    Task.Run(delegate
            //    {
            //        IAdminOperationRecordService operationRecordService = partnerAppController.HttpContext.RequestServices.GetService<IAdminOperationRecordService>();

            //        operationRecordService.Create(this.name, this.ConvertActionArguments(), partnerAppController.User.UserId, partnerAppController.User.Phone, partnerAppController.User.Fullname);
            //    });
            //}
        }

        private string ConvertActionArguments()
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();

            foreach (var item in this.actionArguments)
            {
                this.Extract(ref dictionary, item.Key, item.Value);
            }

            return JsonConvert.SerializeObject(dictionary);
        }

        private void Extract(ref Dictionary<string, string> dictionary, string key, object obj)
        {
            if (obj.GetType().FullName.StartsWith("System.Collections.Generic.Dictionary"))
            {
                string jsonStr = JsonConvert.SerializeObject(obj);
                dictionary.Add(key + ".object", jsonStr);
                return;
            }
            foreach (var item in obj.GetType().GetProperties())
            {
                string currentKey = $"{key}.{item.Name}";
                //item.PropertyType == typeof(string) && item.ReflectedType ? "" :
                if (item.ReflectedType.Name == "List`1")
                {
                    dictionary.Add(currentKey, JsonConvert.SerializeObject(obj));
                    continue;
                }
                object currentObj = item.PropertyType == typeof(char) ? obj : item.PropertyType == typeof(string) && item.ReflectedType.Name == "List`1" ? "枚举类型" : item.GetValue(obj);

                if (currentObj == null)
                {
                    continue;
                }

                if (item.PropertyType == typeof(bool?) || item.PropertyType == typeof(bool?) ||
                    item.PropertyType == typeof(byte) || item.PropertyType == typeof(sbyte) || item.PropertyType == typeof(byte?) || item.PropertyType == typeof(sbyte?) ||
                    item.PropertyType == typeof(short) || item.PropertyType == typeof(ushort) || item.PropertyType == typeof(short?) || item.PropertyType == typeof(ushort?) ||
                    item.PropertyType == typeof(int) || item.PropertyType == typeof(uint) || item.PropertyType == typeof(int?) || item.PropertyType == typeof(uint?) ||
                    item.PropertyType == typeof(long) || item.PropertyType == typeof(ulong) || item.PropertyType == typeof(long?) || item.PropertyType == typeof(ulong?) ||
                    item.PropertyType == typeof(char) || item.PropertyType == typeof(char?) ||
                    item.PropertyType == typeof(float) || item.PropertyType == typeof(double) || item.PropertyType == typeof(float?) || item.PropertyType == typeof(double?) ||
                    item.PropertyType == typeof(decimal) || item.PropertyType == typeof(decimal?) ||
                    item.PropertyType == typeof(DateTime) || item.PropertyType == typeof(DateTime?) ||
                    item.PropertyType == typeof(string))
                {
                    // 处理常见的一些敏感数据。
                    if (currentKey.IndexOf("PASSWORD", StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        dictionary.Add(currentKey, "***");
                    }
                    else if (currentKey.IndexOf("PHONE", StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        string phone = currentObj.ToString();

                        if (phone.Length > 4)
                        {
                            phone = "*" + phone.Substring(phone.Length - 4);
                        }

                        dictionary.Add(currentKey, phone);
                    }
                    else if (currentKey.IndexOf("EMAIL", StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        string email = currentObj.ToString();
                        int atIndex = email.IndexOf("@");

                        if (atIndex > -1)
                        {
                            email = email.Substring(0, atIndex + 1) + "***" + email.Substring(email.IndexOf(".", atIndex));
                        }

                        dictionary.Add(currentKey, email);
                    }
                    else if (currentKey.IndexOf("IDENTITY", StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        string identityCard = currentObj.ToString();

                        if (identityCard.Length > 8)
                        {
                            identityCard = identityCard.Substring(0, 4) + "***" + identityCard.Substring(identityCard.Length - 4);
                        }

                        dictionary.Add(currentKey, identityCard);
                    }
                    else
                    {
                        dictionary.Add(currentKey, currentObj.ToString());
                    }
                }
                else if (obj.GetType().IsArray)
                {
                    foreach (var newObj in obj as Array)
                    {
                        this.Extract(ref dictionary, currentKey, newObj);
                    }
                }
                else
                {
                    this.Extract(ref dictionary, currentKey, currentObj);
                }
            }
        }
    }
}
